home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tar.gnu / sprite / buffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-29  |  29.3 KB  |  1,345 lines

  1. /* Buffer management for tar.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Buffer management for tar.
  22.  *
  23.  * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
  24.  *
  25.  * @(#) buffer.c 1.28 11/6/87 - gnu
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <errno.h>
  30. #include <sys/types.h>        /* For non-Berkeley systems */
  31. #include <sys/stat.h>
  32. #include <sys/wait.h>
  33. #include <signal.h>
  34. #include <assert.h>
  35.  
  36. #ifndef MSDOS
  37. #include <sys/ioctl.h>
  38. #ifndef USG
  39. #include <sys/mtio.h>
  40. #endif
  41. #endif
  42.  
  43. #ifdef    MSDOS
  44. # include <fcntl.h>
  45. #include <process.h>
  46. #else
  47. # ifdef XENIX
  48. #  include <sys/inode.h>
  49. # endif
  50. # include <sys/file.h>
  51. #endif
  52.  
  53. extern int errno;
  54. extern union record *head;
  55.  
  56. #include "tar.h"
  57. #include "port.h"
  58. #include "rmt.h"
  59.  
  60. /* Either stdout or stderr:  The thing we write messages (standard msgs, not
  61.    errors) to.  Stdout unless we're writing a pipe, in which case stderr */
  62. FILE *msg_file = stdout;
  63.  
  64. #define    STDIN    0        /* Standard input  file descriptor */
  65. #define    STDOUT    1        /* Standard output file descriptor */
  66.  
  67. #define    PREAD    0        /* Read  file descriptor from pipe() */
  68. #define    PWRITE    1        /* Write file descriptor from pipe() */
  69.  
  70. #ifdef __GNU__
  71. extern void    *malloc();
  72. extern void    *valloc();
  73. #else
  74. extern char    *malloc();
  75. extern char    *valloc();
  76. #endif
  77.  
  78. extern char    *index(), *strcat();
  79. extern char    *strcpy();
  80.  
  81. /*
  82.  * V7 doesn't have a #define for this.
  83.  */
  84. #ifndef O_RDONLY
  85. #define    O_RDONLY    0
  86. #endif
  87. #ifndef O_RDWR
  88. #define O_RDWR        2
  89. #endif
  90. #ifndef O_CREAT
  91. #define O_CREAT        0
  92. #endif
  93. #ifndef O_BINARY
  94. #define O_BINARY    0
  95. #endif
  96.  
  97. #define    MAGIC_STAT    105    /* Magic status returned by child, if
  98.                    it can't exec.  We hope compress/sh
  99.                    never return this status! */
  100.  
  101. static void _writeerror();
  102. #define writeerror(err)     _writeerror(err, __LINE__)
  103.  
  104. void readerror();
  105.  
  106. void ck_pipe();
  107. void ck_close();
  108.  
  109. extern void finish_header();
  110.  
  111. /*
  112.  * The record pointed to by save_rec should not be overlaid
  113.  * when reading in a new tape block.  Copy it to record_save_area first, and
  114.  * change the pointer in *save_rec to point to record_save_area.
  115.  * Saved_recno records the record number at the time of the save.
  116.  * This is used by annofile() to print the record number of a file's
  117.  * header record.
  118.  */
  119. static union record **save_rec;
  120.  union record record_save_area;
  121. static long        saved_recno;
  122.  
  123. /*
  124.  * PID of child program, if f_compress or remote archive access.
  125.  */
  126. static int    childpid = 0;
  127.  
  128. /*
  129.  * Record number of the start of this block of records
  130.  */
  131. long    baserec;
  132.  
  133. /*
  134.  * Error recovery stuff
  135.  */
  136. static int    r_error_count;
  137.  
  138. /*
  139.  * Have we hit EOF yet?
  140.  */
  141. static int    eof;
  142.  
  143. /* JF we're reading, but we just read the last record and its time to update */
  144. extern time_to_start_writing;
  145. int file_to_switch_to= -1;    /* If remote update, close archive, and use
  146.                    this descriptor to write to */
  147.  
  148. static int volno = 1;        /* JF which volume of a multi-volume tape
  149.                    we're on */
  150.  
  151. char *save_name = 0;        /* Name of the file we are currently writing */
  152. long save_totsize;        /* total size of file we are writing.  Only
  153.                    valid if save_name is non_zero */
  154. long save_sizeleft;        /* Where we are in the file we are writing.
  155.                    Only valid if save_name is non-zero */
  156.  
  157. int write_archive_to_stdout;
  158.  
  159. /* Used by fl_read and fl_write to store the real info about saved names */
  160. static char real_s_name[NAMSIZ];
  161. static long real_s_totsize;
  162. static long real_s_sizeleft;
  163.  
  164. /*
  165.  * Return the location of the next available input or output record.
  166.  * Return NULL for EOF.  Once we have returned NULL, we just keep returning
  167.  * it, to avoid accidentally going on to the next file on the "tape".
  168.  * 
  169.  * Side effects:
  170.  *     Might move the saved record (if any), invalidating any saved
  171.  *     pointers into it.
  172.  */
  173. union record *
  174. findrec()
  175. {
  176.     if (ar_record == ar_last) {
  177.         if (eof)
  178.             return (union record *)NULL;    /* EOF */
  179.         flush_archive();
  180.         if (ar_record == ar_last) {
  181.             eof++;
  182.             return (union record *)NULL;    /* EOF */
  183.         }
  184.     }
  185.     return ar_record;
  186. }
  187.  
  188.  
  189. /*
  190.  * Indicate that we have used all records up thru the argument.
  191.  * (should the arg have an off-by-1? XXX FIXME)
  192.  */
  193. void
  194. userec(rec)
  195.     union record *rec;
  196. {
  197.     while(rec >= ar_record)
  198.         ar_record++;
  199.     /*
  200.      * Do NOT flush the archive here.  If we do, the same
  201.      * argument to userec() could mean the next record (if the
  202.      * input block is exactly one record long), which is not what
  203.      * is intended.
  204.      */
  205.     if (ar_record > ar_last)
  206.         abort();
  207. }
  208.  
  209.  
  210. /*
  211.  * Return a pointer to the end of the current records buffer.
  212.  * All the space between findrec() and endofrecs() is available
  213.  * for filling with data, or taking data from.
  214.  */
  215. union record *
  216. endofrecs()
  217. {
  218.     return ar_last;
  219. }
  220.  
  221.  
  222. /*
  223.  * Duplicate a file descriptor into a certain slot.
  224.  * Equivalent to BSD "dup2" with error reporting.
  225.  */
  226. void
  227. dupto(from, to, msg)
  228.     int from, to;
  229.     char *msg;
  230. {
  231.     int err;
  232.  
  233.     if (from != to) {
  234.         err=close(to);
  235.         if(err<0 && errno!=EBADF) {
  236.             msg_perror("Cannot close descriptor %d",to);
  237.             exit(EX_SYSTEM);
  238.         }
  239.         err = dup(from);
  240.         if (err != to) {
  241.             msg_perror("cannot dup %s",msg);
  242.             exit(EX_SYSTEM);
  243.         }
  244.         ck_close(from);
  245.     }
  246. }
  247.  
  248. #ifdef MSDOS
  249. void
  250. child_open()
  251. {
  252.     fprintf(stderr,"MSDOS %s can't use compressed or remote archives\n",tar);
  253.     exit(EX_ARGSBAD);
  254. }
  255. #else
  256. void
  257. child_open()
  258. {
  259.     int pipe[2];
  260.     int err = 0;
  261.  
  262.     int kidpipe[2];
  263.     int kidchildpid;
  264.  
  265. #define READ    0
  266. #define WRITE    1
  267.  
  268.     ck_pipe(pipe);
  269.  
  270.     childpid=fork();
  271.     if(childpid<0) {
  272.         msg_perror("cannot fork");
  273.         exit(EX_SYSTEM);
  274.     }
  275.     if(childpid>0) {
  276.         /* We're the parent.  Clean up and be happy */
  277.         /* This, at least, is easy */
  278.  
  279.         if(ar_reading) {
  280.             f_reblock++;
  281.             archive=pipe[READ];
  282.             ck_close(pipe[WRITE]);
  283.         } else {
  284.             archive = pipe[WRITE];
  285.             ck_close(pipe[READ]);
  286.         }
  287.         return;
  288.     }
  289.  
  290.     /* We're the kid */
  291.     if(ar_reading) {
  292.         dupto(pipe[WRITE],STDOUT,"(child) pipe to stdout");
  293.         ck_close(pipe[READ]);
  294.     } else {
  295.         dupto(pipe[READ],STDIN,"(child) pipe to stdin");
  296.         ck_close(pipe[WRITE]);
  297.     }
  298.  
  299.     /* We need a child tar only if
  300.        1: we're reading/writing stdin/out (to force reblocking)
  301.        2: the file is to be accessed by rmt (compress doesn't know how)
  302.        3: the file is not a plain file */
  303. #ifdef NO_REMOTE
  304.     if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file))
  305. #else
  306.     if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file))
  307. #endif
  308.     {
  309.         /* We don't need a child tar.  Open the archive */
  310.         if(ar_reading) {
  311.             archive=open(ar_file, O_RDONLY|O_BINARY, 0666);
  312.             if(archive<0) {
  313.                 msg_perror("can't open archive %s",ar_file);
  314.                 exit(EX_BADARCH);
  315.             }
  316.             dupto(archive,STDIN,"archive to stdin");
  317.             /* close(archive); */
  318.         } else {
  319.             archive=creat(ar_file,0666);
  320.             if(archive<0) {
  321.                 msg_perror("can't open archive %s",ar_file);
  322.                 exit(EX_BADARCH);
  323.             }
  324.             dupto(archive,STDOUT,"archive to stdout");
  325.             /* close(archive); */
  326.         }
  327.     } else {
  328.         /* We need a child tar */
  329.         ck_pipe(kidpipe);
  330.  
  331.         kidchildpid=fork();
  332.         if(kidchildpid<0) {
  333.             msg_perror("child can't fork");
  334.             exit(EX_SYSTEM);
  335.         }
  336.  
  337.         if(kidchildpid>0) {
  338.             /* About to exec compress:  set up the files */
  339.             if(ar_reading) {
  340.                 dupto(kidpipe[READ],STDIN,"((child)) pipe to stdin");
  341.                 ck_close(kidpipe[WRITE]);
  342.                 /* dup2(pipe[WRITE],STDOUT); */
  343.             } else {
  344.                 /* dup2(pipe[READ],STDIN); */
  345.                 dupto(kidpipe[WRITE],STDOUT,"((child)) pipe to stdout");
  346.                 ck_close(kidpipe[READ]);
  347.             }
  348.             /* ck_close(pipe[READ]); */
  349.             /* ck_close(pipe[WRITE]); */
  350.             /* ck_close(kidpipe[READ]);
  351.             ck_close(kidpipe[WRITE]); */
  352.         } else {
  353.         /* Grandchild.  Do the right thing, namely sit here and
  354.            read/write the archive, and feed stuff back to compress */
  355.             tar="tar (child)";
  356.             if(ar_reading) {
  357.                 dupto(kidpipe[WRITE],STDOUT,"[child] pipe to stdout");
  358.                 ck_close(kidpipe[READ]);
  359.             } else {
  360.                 dupto(kidpipe[READ],STDIN,"[child] pipe to stdin");
  361.                 ck_close(kidpipe[WRITE]);
  362.             }
  363.  
  364.             if (ar_file[0] == '-' && ar_file[1] == '\0') {
  365.                 if (ar_reading)
  366.                     archive = STDIN;
  367.                 else
  368.                     archive = STDOUT;
  369.             } else /* This can't happen if (ar_reading==2)
  370.                 archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
  371.             else */if(ar_reading)
  372.                 archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666);
  373.             else
  374.                 archive = rmtcreat(ar_file, 0666);
  375.  
  376.             if (archive < 0) {
  377.                 msg_perror("can't open archive %s",ar_file);
  378.                 exit(EX_BADARCH);
  379.             }
  380.  
  381.             if(ar_reading) {
  382.                 for(;;) {
  383.                     char *ptr;
  384.                     int max,count;
  385.         
  386.                     r_error_count = 0;
  387.                 error_loop:
  388.                     err=rmtread(archive, ar_block->charptr,(int)(blocksize));
  389.                     if(err<0) {
  390.                         readerror();
  391.                         goto error_loop;
  392.                     }
  393.                     if(err==0)
  394.                         break;
  395.                     ptr = ar_block->charptr;
  396.                     max = err;
  397.                     while(max) {
  398.                         count = (max<RECORDSIZE) ? max : RECORDSIZE;
  399.                         err=write(STDOUT,ptr,count);
  400.                         if(err!=count) {
  401.                             if(err<0) {
  402.                                 msg_perror("can't write to compress");
  403.                                 exit(EX_SYSTEM);
  404.                             } else
  405.                                 msg("write to compress short %d bytes",count-err);
  406.                             count = (err<0) ? 0 : err;
  407.                         }
  408.                         ptr+=count;
  409.                         max-=count;
  410.                     }
  411.                 }
  412.             } else {
  413.                 for(;;) {
  414.                     int n;
  415.                     char *ptr;
  416.         
  417.                     n=blocksize;
  418.                     ptr = ar_block->charptr;
  419.                     while(n) {
  420.                         err=read(STDIN,ptr,(n<RECORDSIZE) ? n : RECORDSIZE);
  421.                         if(err<=0)
  422.                             break;
  423.                         n-=err;
  424.                         ptr+=err;
  425.                     }
  426.                         /* EOF */
  427.                     if(err==0) {
  428.                         if(f_compress<2)
  429.                             blocksize-=n;
  430.                         else
  431.                             bzero(ar_block->charptr+n,blocksize-n);
  432.                         err=rmtwrite(archive,ar_block->charptr,blocksize);
  433.                         if(err!=(blocksize))
  434.                             writeerror(err);
  435.                         if(f_compress<2)
  436.                             blocksize+=n;
  437.                         break;
  438.                     }
  439.                     if(n) {
  440.                         msg_perror("can't read from compress");
  441.                         exit(EX_SYSTEM);
  442.                     }
  443.                     err=rmtwrite(archive, ar_block->charptr, (int)blocksize);
  444.                     if(err!=blocksize)
  445.                         writeerror(err);
  446.                 }
  447.             }
  448.         
  449.             /* close_archive(); */
  450.             if (f_debug) {
  451.                 fprintf(stderr, "Tar.gnu: exiting normally\n");
  452.             }
  453.             exit(0);
  454.         }
  455.     }
  456.         /* So we should exec compress (-d) */
  457.     if(ar_reading)
  458.         execlp("compress", "compress", "-d", (char *)0);
  459.     else
  460.         execlp("compress", "compress", (char *)0);
  461.     msg_perror("can't exec compress");
  462.     _exit(EX_SYSTEM);
  463. }
  464.  
  465.  
  466. /* return non-zero if p is the name of a directory */
  467. isfile(p)
  468. char *p;
  469. {
  470.     struct stat stbuf;
  471.  
  472.     if(stat(p,&stbuf)<0)
  473.         return 1;
  474.     if((stbuf.st_mode&S_IFMT)==S_IFREG)
  475.         return 1;
  476.     return 0;
  477. }
  478.  
  479. #endif
  480.  
  481. /*
  482.  * Open an archive file.  The argument specifies whether we are
  483.  * reading or writing.
  484.  */
  485. /* JF if the arg is 2, open for reading and writing. */
  486. open_archive(reading)
  487.     int reading;
  488. {
  489.     msg_file = stdout;
  490.  
  491.     if (blocksize == 0) {
  492.         msg("invalid value for blocksize");
  493.         exit(EX_ARGSBAD);
  494.     }
  495.  
  496.     if(ar_file==0) {
  497.         msg("No archive name given, what should I do?");
  498.         exit(EX_BADARCH);
  499.     }
  500.  
  501.     /*NOSTRICT*/
  502.     if(f_multivol) {
  503.         ar_block = (union record *) valloc((unsigned)(blocksize+(2*RECORDSIZE)));
  504.         if(ar_block)
  505.             ar_block += 2;
  506.     } else
  507.         ar_block = (union record *) valloc((unsigned)blocksize);
  508.     if (!ar_block) {
  509.         msg("could not allocate memory for blocking factor %d",
  510.             blocking);
  511.         exit(EX_ARGSBAD);
  512.     }
  513.  
  514.     ar_record = ar_block;
  515.     ar_last   = ar_block + blocking;
  516.     ar_reading = reading;
  517.  
  518.     if (f_compress) {
  519.         if(reading==2 || f_verify) {
  520.             msg("cannot update or verify compressed archives");
  521.             exit(EX_ARGSBAD);
  522.         }
  523.         child_open();
  524.         if(!reading && ar_file[0]=='-' && ar_file[1]=='\0')
  525.             msg_file = stderr;
  526.         /* child_open(rem_host, rem_file); */
  527.     } else if (ar_file[0] == '-' && ar_file[1] == '\0') {
  528.         f_reblock++;    /* Could be a pipe, be safe */
  529.         if(f_verify) {
  530.             msg("can't verify stdin/stdout archive");
  531.             exit(EX_ARGSBAD);
  532.         }
  533.         if(reading==2) {
  534.             archive=STDIN;
  535.             msg_file=stderr;
  536.             write_archive_to_stdout++;
  537.         } else if (reading)
  538.             archive = STDIN;
  539.         else {
  540.             archive = STDOUT;
  541.             msg_file = stderr;
  542.         }
  543.     } else if (reading==2 || f_verify) {
  544.         archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
  545.     } else if(reading) {
  546.         archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666);
  547.     } else {
  548.         archive = rmtcreat(ar_file, 0666);
  549.     }
  550.  
  551.     if (archive < 0) {
  552.         msg_perror("can't open %s",ar_file);
  553.         exit(EX_BADARCH);
  554.     }
  555. #ifdef    MSDOS
  556.     setmode(archive, O_BINARY);
  557. #endif
  558.  
  559.     if (reading) {
  560.         ar_last = ar_block;        /* Set up for 1st block = # 0 */
  561.         (void) findrec();        /* Read it in, check for EOF */
  562.  
  563.         if(f_volhdr) {
  564.             union record *header;
  565.             char *ptr;
  566.  
  567.             if(f_multivol) {
  568.                 ptr=malloc(strlen(f_volhdr)+20);
  569.                 sprintf(ptr,"%s Volume %d",f_volhdr,1);
  570.             } else
  571.                 ptr=f_volhdr;
  572.             header=findrec();
  573.             if(!header) {
  574.                 fprintf(stderr, "Null input\n");
  575.                 exit(EX_BADARCH);
  576.             }
  577.             if(strcmp(ptr,header->header.name)) {
  578.                 msg("Volume mismatch!  %s!=%s\n",ptr,header->header.name);
  579.                 exit(EX_BADARCH);
  580.             }
  581.             if(ptr!=f_volhdr)
  582.                 free(ptr);
  583.         }
  584.     } else if(f_volhdr) {
  585.         bzero((void *)ar_block,RECORDSIZE);
  586.         if(f_multivol)
  587.             sprintf(ar_block->header.name,"%s Volume 1",f_volhdr);
  588.         else
  589.             strcpy(ar_block->header.name,f_volhdr);
  590.         ar_block->header.linkflag = LF_VOLHDR;
  591.         finish_header(ar_block);
  592.         /* ar_record++; */
  593.     }
  594. }
  595.  
  596.  
  597. /*
  598.  * Remember a union record * as pointing to something that we
  599.  * need to keep when reading onward in the file.  Only one such
  600.  * thing can be remembered at once, and it only works when reading
  601.  * an archive.
  602.  *
  603.  * We calculate "offset" then add it because some compilers end up
  604.  * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
  605.  * subtracting ar_block from that, shifting it back, losing the top 9 bits.
  606.  */
  607. saverec(pointer)
  608.     union record **pointer;
  609. {
  610.     long offset;
  611. #if 0
  612.     static num_saved;
  613.  
  614.     if (pointer == NULL) {
  615.         assert(num_saved == 1);
  616.         num_saved = 0;
  617.     } else {
  618.         assert(num_saved == 0);
  619.         num_saved = 1;
  620.     }
  621. #endif
  622.     assert(pointer == NULL || pointer == &head);
  623.     assert(save_rec == NULL || save_rec == &head);
  624.     if (save_rec != NULL && pointer != NULL) {
  625.         msg("Warning: saving a record over another one.");
  626.     }
  627.     save_rec = pointer;
  628.     offset = ar_record - ar_block;
  629.     saved_recno = baserec + offset;
  630. }
  631.  
  632. /*
  633.  * Perform a write to flush the buffer.
  634.  */
  635.  
  636. /*send_buffer_to_file();
  637.   if(new_volume) {
  638.       deal_with_new_volume_stuff();
  639.     send_buffer_to_file();
  640.   }
  641.  */
  642.  
  643. fl_write()
  644. {
  645.     int err;
  646.     int copy_back;
  647. #ifdef TEST
  648.     static long test_written = 0;
  649. #endif
  650.  
  651. #ifdef TEST
  652.     if(test_written>=30720) {
  653.         errno = ENOSPC;
  654.         err = 0;
  655.     } else
  656. #endif
  657.     err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
  658.     if(err!=blocksize && !f_multivol)
  659.         writeerror(err);
  660.  
  661. #ifdef TEST
  662.     if(err>0)
  663.         test_written+=err;
  664. #endif
  665.     if (err == blocksize) {
  666.         if(f_multivol) {
  667.             if(!save_name) {
  668.                 real_s_name[0]='\0';
  669.                 real_s_totsize=0;
  670.                 real_s_sizeleft = 0;
  671.                 return;
  672.             }
  673. #ifdef MSDOS
  674.             if(save_name[1]==':')
  675.                 save_name+=2;
  676. #endif
  677.             while(*save_name=='/')
  678.                 save_name++;
  679.  
  680.             strcpy(real_s_name,save_name);
  681.             real_s_totsize = save_totsize;
  682.             real_s_sizeleft = save_sizeleft;
  683.         }
  684.         return;
  685.     }
  686.  
  687.     /* We're multivol  Panic if we didn't get the right kind of response */
  688.     /* ENXIO is for the UNIX PC */
  689.     if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO))
  690.         writeerror(err);
  691.  
  692.     if(new_volume(0)<0)
  693.         return;
  694. #ifdef TEST
  695.     test_written=0;
  696. #endif
  697.     if(f_volhdr && real_s_name[0]) {
  698.         copy_back=2;
  699.         ar_block-=2;
  700.     } else if(f_volhdr || real_s_name[0]) {
  701.         copy_back = 1;
  702.         ar_block--;
  703.     } else
  704.         copy_back = 0;
  705.     if(f_volhdr) {
  706.         bzero((void *)ar_block,RECORDSIZE);
  707.         sprintf(ar_block->header.name,"%s Volume %d",f_volhdr,volno);
  708.         ar_block->header.linkflag = LF_VOLHDR;
  709.         finish_header(ar_block);
  710.     }
  711.     if(real_s_name[0]) {
  712.         extern void to_oct();
  713.         int tmp;
  714.  
  715.         if(f_volhdr)
  716.             ar_block++;
  717.         bzero((void *)ar_block,RECORDSIZE);
  718.         strcpy(ar_block->header.name,real_s_name);
  719.         ar_block->header.linkflag = LF_MULTIVOL;
  720.         to_oct((long)real_s_sizeleft,1+12,
  721.                ar_block->header.size);
  722.         to_oct((long)real_s_totsize-real_s_sizeleft,
  723.                1+12,ar_block->header.offset);
  724.         tmp=f_verbose;
  725.         f_verbose=0;
  726.         finish_header(ar_block);
  727.         f_verbose=tmp;
  728.         if(f_volhdr)
  729.             ar_block--;
  730.     }
  731.  
  732.     err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
  733.     if(err!=blocksize)
  734.         writeerror(err);
  735.  
  736. #ifdef TEST
  737.     test_written = blocksize;
  738. #endif
  739.     if(copy_back) {
  740.         ar_block+=copy_back;
  741.         bcopy((void *)(ar_block+blocking-copy_back),
  742.               (void *)ar_record,
  743.               copy_back*RECORDSIZE);
  744.         ar_record+=copy_back;
  745.  
  746.         if(real_s_sizeleft>=copy_back*RECORDSIZE)
  747.             real_s_sizeleft-=copy_back*RECORDSIZE;
  748.         else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back)
  749.             real_s_name[0] = '\0';
  750.         else {
  751. #ifdef MSDOS
  752.             if(save_name[1]==':')
  753.                 save_name+=2;
  754. #endif
  755.             while(*save_name=='/')
  756.                 save_name++;
  757.  
  758.             strcpy(real_s_name,save_name);
  759.             real_s_sizeleft = save_sizeleft;
  760.             real_s_totsize=save_totsize;
  761.         }
  762.         copy_back = 0;
  763.     }
  764. }
  765.  
  766. /* Handle write errors on the archive.  Write errors are always fatal */
  767. /* Hitting the end of a volume does not cause a write error unless the write
  768. *  was the first block of the volume */
  769.  
  770. static void
  771. _writeerror(err, line)
  772.     int err;
  773.     int line;
  774. {
  775.     if (err < 0) {
  776.         msg_perror("can't write to %s",ar_file);
  777.         fprintf(stderr, "line = %d\n", line);
  778.         exit(EX_BADARCH);
  779.     } else {
  780.         msg("only wrote %u of %u bytes to %s",err,blocksize,ar_file);
  781.         fprintf(stderr, "line = %d\n", line);
  782.         exit(EX_BADARCH);
  783.     }
  784. }
  785.  
  786. /*
  787.  * Handle read errors on the archive.
  788.  *
  789.  * If the read should be retried, readerror() returns to the caller.
  790.  */
  791. void
  792. readerror()
  793. {
  794. #    define    READ_ERROR_MAX    10
  795.  
  796.     read_error_flag++;        /* Tell callers */
  797.  
  798.     msg_perror("read error on %s",ar_file);
  799.  
  800.     if (baserec == 0) {
  801.         /* First block of tape.  Probably stupidity error */
  802.         exit(EX_BADARCH);
  803.     }
  804.  
  805.     /*
  806.      * Read error in mid archive.  We retry up to READ_ERROR_MAX times
  807.      * and then give up on reading the archive.  We set read_error_flag
  808.      * for our callers, so they can cope if they want.
  809.      */
  810.     if (r_error_count++ > READ_ERROR_MAX) {
  811.         msg("Too many errors, quitting.");
  812.         exit(EX_BADARCH);
  813.     }
  814.     return;
  815. }
  816.  
  817.  
  818. /*
  819.  * Perform a read to flush the buffer.
  820.  */
  821. fl_read()
  822. {
  823.     int err;        /* Result from system call */
  824.     int left;        /* Bytes left */
  825.     char *more;        /* Pointer to next byte to read */
  826.  
  827.     /*
  828.      * Clear the count of errors.  This only applies to a single
  829.      * call to fl_read.  We leave read_error_flag alone; it is
  830.      * only turned off by higher level software.
  831.      */
  832.     r_error_count = 0;    /* Clear error count */
  833.  
  834.     /*
  835.      * If we are about to wipe out a record that
  836.      * somebody needs to keep, copy it out to a holding
  837.      * area and adjust somebody's pointer to it.
  838.      */
  839.     if (save_rec &&
  840.         *save_rec >= ar_record &&
  841.         *save_rec < ar_last) {
  842.         record_save_area = **save_rec;
  843.         *save_rec = &record_save_area;
  844.     }
  845.     if(write_archive_to_stdout && baserec!=0) {
  846.         err=rmtwrite(1, ar_block->charptr, blocksize);
  847.         if(err!=blocksize)
  848.             writeerror(err);
  849.     }
  850.     if(f_multivol) {
  851.         if(save_name) {
  852.             if(save_name!=real_s_name) {
  853. #ifdef MSDOS
  854.                 if(save_name[1]==':')
  855.                     save_name+=2;
  856. #endif
  857.                 while(*save_name=='/')
  858.                     save_name++;
  859.  
  860.                 strcpy(real_s_name,save_name);
  861.                 save_name=real_s_name;
  862.             }
  863.             real_s_totsize = save_totsize;
  864.             real_s_sizeleft = save_sizeleft;
  865.                 
  866.         } else {
  867.             real_s_name[0]='\0';
  868.             real_s_totsize=0;
  869.             real_s_sizeleft = 0;
  870.         }
  871.     }
  872.  
  873. error_loop:
  874.     err = rmtread(archive, ar_block->charptr, (int)blocksize);
  875.     if (err == blocksize)
  876.         return;
  877.  
  878.     if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) {
  879.         union record *header;
  880.  
  881.     try_volume:
  882.         if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0)
  883.             return;
  884.     vol_error:
  885.         err = rmtread(archive, ar_block->charptr,(int) blocksize);
  886.         if(err < 0) {
  887.             readerror();
  888.             goto vol_error;
  889.         }
  890.         if(err!=blocksize)
  891.             goto short_read;
  892.  
  893.         header=ar_block;
  894.  
  895.         if(header->header.linkflag==LF_VOLHDR) {
  896.             if(f_volhdr) {
  897.                 char *ptr;
  898.  
  899.                 ptr=(char *)malloc(strlen(f_volhdr)+20);
  900.                 sprintf(ptr,"%s Volume %d",f_volhdr,volno);
  901.                 if(strcmp(ptr,header->header.name)) {
  902.                     msg("Volume mismatch! %s!=%s\n",ptr,header->header.name);
  903.                     --volno;
  904.                     free(ptr);
  905.                     goto try_volume;
  906.                 }
  907.                 free(ptr);
  908.             }
  909.             if(f_verbose)
  910.                 fprintf(msg_file,"Reading %s\n",header->header.name);
  911.             header++;
  912.         } else if(f_volhdr) {
  913.             msg("Warning:  No volume header!");
  914.         }
  915.  
  916.         if(real_s_name[0]) {
  917.             long from_oct();
  918.  
  919.             if(header->header.linkflag!=LF_MULTIVOL || strcmp(header->header.name,real_s_name)) {
  920.                 msg("%s is not continued on this volume!",real_s_name);
  921.                 --volno;
  922.                 goto try_volume;
  923.             }
  924.             if(real_s_totsize!=from_oct(1+12,header->header.size)+from_oct(1+12,header->header.offset)) {
  925.                 msg("%s is the wrong size (%ld!=%ld+%ld)",
  926.                        header->header.name,save_totsize,
  927.                        from_oct(1+12,header->header.size),
  928.                        from_oct(1+12,header->header.offset));
  929.                 --volno;
  930.                 goto try_volume;
  931.             }
  932.             if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,header->header.offset)) {
  933.                 msg("This volume is out of sequence");
  934.                 --volno;
  935.                 goto try_volume;
  936.             }
  937.             header++;
  938.         }
  939.         ar_record=header;
  940.         return;
  941.     } else if (err < 0) {
  942.         readerror();
  943.         goto error_loop;    /* Try again */
  944.     }
  945.  
  946.  short_read:
  947.     more = ar_block->charptr + err;
  948.     left = blocksize - err;
  949.  
  950. again:
  951.     if (0 == (((unsigned)left) % RECORDSIZE)) {
  952.         /* FIXME, for size=0, multi vol support */
  953.         /* On the first block, warn about the problem */
  954.         if (!f_reblock && baserec == 0 && f_verbose && err > 0) {
  955.         /*    msg("Blocksize = %d record%s",
  956.                 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
  957.             msg("Blocksize = %d records", err / RECORDSIZE);
  958.         }
  959.         ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE;
  960.         return;
  961.     }
  962.     if (f_reblock) {
  963.         /*
  964.          * User warned us about this.  Fix up.
  965.          */
  966.         if (left > 0) {
  967. error2loop:
  968.             err = rmtread(archive, more, (int)left);
  969.             if (err < 0) {
  970.                 readerror();
  971.                 goto error2loop;    /* Try again */
  972.             }
  973.             if (err == 0) {
  974.                 msg("archive %s EOF not on block boundary",ar_file);
  975.                 exit(EX_BADARCH);
  976.             }
  977.             left -= err;
  978.             more += err;
  979.             goto again;
  980.         }
  981.     } else {
  982.         msg("only read %d bytes from archive %s",err,ar_file);
  983.         exit(EX_BADARCH);
  984.     }
  985. }
  986.  
  987.  
  988. /*
  989.  * Flush the current buffer to/from the archive.
  990.  */
  991. flush_archive()
  992. {
  993.     baserec += ar_last - ar_block;    /* Keep track of block #s */
  994.     ar_record = ar_block;        /* Restore pointer to start */
  995.     ar_last = ar_block + blocking;    /* Restore pointer to end */
  996.  
  997.     if (ar_reading) {
  998.         if(time_to_start_writing) {
  999.             time_to_start_writing=0;
  1000.             ar_reading=0;
  1001.  
  1002.             if(file_to_switch_to>=0) {
  1003.                 rmtclose(archive);
  1004.                 archive=file_to_switch_to;
  1005.             } else
  1006.                  (void)backspace_output();
  1007.             fl_write();
  1008.         } else
  1009.             fl_read();
  1010.     } else {
  1011.         fl_write();
  1012.     }
  1013. }
  1014.  
  1015. /* Backspace the archive descriptor by one blocks worth.
  1016.    If its a tape, MTIOCTOP will work.  If its something else,
  1017.    we try to seek on it.  If we can't seek, we lose! */
  1018. backspace_output()
  1019. {
  1020.     long cur;
  1021.     /* int er; */
  1022.     extern char *output_start;
  1023.  
  1024. #ifdef MTIOCTOP
  1025.     struct mtop t;
  1026.  
  1027.     t.mt_op = MTBSR;
  1028.     t.mt_count = 1;
  1029.     if((rmtioctl(archive,MTIOCTOP,&t))>=0)
  1030.         return 1;
  1031.     if(errno==EIO && (rmtioctl(archive,MTIOCTOP,&t))>=0)
  1032.         return 1;
  1033. #endif
  1034.  
  1035.         cur=rmtlseek(archive,0L,1);
  1036.     cur-=blocksize;
  1037.     /* Seek back to the beginning of this block and
  1038.        start writing there. */
  1039.  
  1040.     if(rmtlseek(archive,cur,0)!=cur) {
  1041.         /* Lseek failed.  Try a different method */
  1042.         msg("Couldn't backspace archive file.  It may be unreadable without -i.");
  1043.         /* Replace the first part of the block with nulls */
  1044.         if(ar_block->charptr!=output_start)
  1045.             bzero(ar_block->charptr,output_start-ar_block->charptr);
  1046.         return 2;
  1047.     }
  1048.     return 3;
  1049. }
  1050.  
  1051.  
  1052. /*
  1053.  * Close the archive file.
  1054.  */
  1055. close_archive()
  1056. {
  1057.     int child;
  1058.     int status;
  1059.  
  1060.     if (time_to_start_writing || !ar_reading)
  1061.         flush_archive();
  1062.     if(cmd_mode==CMD_DELETE) {
  1063.         long pos;
  1064.  
  1065.         pos = rmtlseek(archive,0L,1);
  1066. #ifndef MSDOS
  1067.         (void) ftruncate(archive,(off_t)pos);
  1068. #else
  1069.         (void)rmtwrite(archive,"",0);
  1070. #endif
  1071.     }
  1072.     if(f_verify)
  1073.         verify_volume();
  1074.     (void) rmtclose(archive);
  1075.  
  1076. #ifndef    MSDOS
  1077.     if (childpid) {
  1078.         /*
  1079.          * Loop waiting for the right child to die, or for
  1080.          * no more kids.
  1081.          */
  1082.         while (((child = wait(&status)) != childpid) && child != -1)
  1083.             ;
  1084.  
  1085.         if (child != -1) {
  1086.             switch (TERM_SIGNAL(status)) {
  1087.             case 0:
  1088.                 /* Child voluntarily terminated  -- but why? */
  1089.                 if (TERM_VALUE(status) == MAGIC_STAT) {
  1090.                     if (f_debug) {
  1091.                     fprintf(stderr,
  1092.                         "Tar.gnu: child exit abnormally\n");
  1093.                     }
  1094.                     exit(EX_SYSTEM);/* Child had trouble */
  1095.                 }
  1096.                 if (TERM_VALUE(status) == (SIGPIPE + 128)) {
  1097.                     /*
  1098.                      * /bin/sh returns this if its child
  1099.                      * dies with SIGPIPE.  'Sok.
  1100.                      */
  1101.                     break;
  1102.                 } else if (TERM_VALUE(status))
  1103.                     msg("child returned status %d",
  1104.                         TERM_VALUE(status));
  1105.             case SIGPIPE:
  1106.                 break;        /* This is OK. */
  1107.  
  1108.             default:
  1109.                 msg("child died with signal %d%s",
  1110.                  TERM_SIGNAL(status),
  1111.                  TERM_COREDUMP(status)? " (core dumped)": "");
  1112.             }
  1113.         }
  1114.     }
  1115. #endif    /* MSDOS */
  1116. }
  1117.  
  1118.  
  1119. #ifdef DONTDEF
  1120. /*
  1121.  * Message management.
  1122.  *
  1123.  * anno writes a message prefix on stream (eg stdout, stderr).
  1124.  *
  1125.  * The specified prefix is normally output followed by a colon and a space.
  1126.  * However, if other command line options are set, more output can come
  1127.  * out, such as the record # within the archive.
  1128.  *
  1129.  * If the specified prefix is NULL, no output is produced unless the
  1130.  * command line option(s) are set.
  1131.  *
  1132.  * If the third argument is 1, the "saved" record # is used; if 0, the
  1133.  * "current" record # is used.
  1134.  */
  1135. void
  1136. anno(stream, prefix, savedp)
  1137.     FILE    *stream;
  1138.     char    *prefix;
  1139.     int    savedp;
  1140. {
  1141. #    define    MAXANNO    50
  1142.     char    buffer[MAXANNO];    /* Holds annorecment */
  1143. #    define    ANNOWIDTH 13
  1144.     int    space;
  1145.     long    offset;
  1146.     int    save_e;
  1147.  
  1148.     save_e=errno;
  1149.     /* Make sure previous output gets out in sequence */
  1150.     if (stream == stderr)
  1151.         fflush(stdout);
  1152.     if (f_sayblock) {
  1153.         if (prefix) {
  1154.             fputs(prefix, stream);
  1155.             putc(' ', stream);
  1156.         }
  1157.         offset = ar_record - ar_block;
  1158.         (void) sprintf(buffer, "rec %d: ",
  1159.             savedp?    saved_recno:
  1160.                 baserec + offset);
  1161.         fputs(buffer, stream);
  1162.         space = ANNOWIDTH - strlen(buffer);
  1163.         if (space > 0) {
  1164.             fprintf(stream, "%*s", space, "");
  1165.         }
  1166.     } else if (prefix) {
  1167.         fputs(prefix, stream);
  1168.         fputs(": ", stream);
  1169.     }
  1170.     errno=save_e;
  1171. }
  1172. #endif
  1173.  
  1174. /* We've hit the end of the old volume.  Close it and open the next one */
  1175. /* Values for type:  0: writing  1: reading  2: updating */
  1176. new_volume(type)
  1177. int    type;
  1178. {
  1179.     /* int    c; */
  1180.     char    inbuf[80];
  1181.     char    *p;
  1182.     static FILE *read_file = 0;
  1183.     extern int now_verifying;
  1184.     extern char TTY_NAME[];
  1185.     char *getenv();
  1186.  
  1187.     if(!read_file && !f_run_script_at_end)
  1188.         read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin;
  1189.  
  1190.     if(now_verifying)
  1191.         return -1;
  1192.     if(f_verify)
  1193.         verify_volume();
  1194.     if(rmtclose(archive)<0) {
  1195.         msg_perror("can't close %s",ar_file);
  1196.         exit(EX_BADARCH);
  1197.     }
  1198.     volno++;
  1199.     if (f_run_script_at_end)
  1200.         system(info_script);
  1201.     else for(;;) {
  1202.         fprintf(msg_file,"Prepare volume #%d and hit return: ",volno);
  1203.         if(fgets(inbuf,sizeof(inbuf),read_file)==0 || inbuf[0]=='\n')
  1204.             break;
  1205.         switch(inbuf[0]) {
  1206.         case '?':
  1207.         {
  1208.             fprintf(msg_file,"\
  1209.  n [name]   Give a new filename for the next (and subsequent) volume(s)\n\
  1210.  q          Abort tar\n\
  1211.  !          Spawn a subshell\n\
  1212.  ?          Print this list\n");
  1213.         }
  1214.             break;
  1215.  
  1216.         case 'q':    /* Quit */
  1217.             fprintf(msg_file,"No new volume; exiting.\n");
  1218.             if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
  1219.                 msg("Warning:  Archive is INCOMPLETE!");
  1220.             exit(EX_BADARCH);
  1221.  
  1222.         case 'n':    /* Get new file name */
  1223.         {
  1224.             char *q,*r;
  1225.             static char *old_name;
  1226.  
  1227.             for(q= &inbuf[1];*q==' ' || *q=='\t';q++)
  1228.                 ;
  1229.             for(r=q;*r;r++)
  1230.                 if(*r=='\n')
  1231.                     *r='\0';
  1232.             if(old_name)
  1233.                 free(old_name);
  1234.             old_name=p=(char *)malloc((unsigned)(strlen(q)+2));
  1235.             if(p==0) {
  1236.                 msg("Can't allocate memory for name");
  1237.                 exit(EX_SYSTEM);
  1238.             }
  1239.             (void) strcpy(p,q);
  1240.             ar_file=p;
  1241.         }
  1242.             break;
  1243.  
  1244.         case '!':
  1245. #ifdef MSDOS
  1246.             spawnl(P_WAIT,getenv("COMSPEC"),"-",0);
  1247. #else
  1248.                 /* JF this needs work! */
  1249.             switch(fork()) {
  1250.             case -1:
  1251.                 msg_perror("can't fork!");
  1252.                 break;
  1253.             case 0:
  1254.                 p=getenv("SHELL");
  1255.                 if(p==0) p="/bin/sh";
  1256.                 execlp(p,"-sh","-i",0);
  1257.                 msg_perror("can't exec a shell %s",p);
  1258.                 _exit(55);
  1259.             default:
  1260.                 wait((union wait *)0);
  1261.                 break;
  1262.             }
  1263. #endif
  1264.             break;
  1265.         }
  1266.     }
  1267.  
  1268.     if(type==2 || f_verify)
  1269.         archive=rmtopen(ar_file,O_RDWR|O_CREAT,0666);
  1270.     else if(type==1)
  1271.         archive=rmtopen(ar_file,O_RDONLY,0666);
  1272.     else if(type==0)
  1273.         archive=rmtcreat(ar_file,0666);
  1274.     else
  1275.         archive= -1;
  1276.  
  1277.     if(archive<0) {
  1278.         msg_perror("can't open %s",ar_file);
  1279.         exit(EX_BADARCH);
  1280.     }
  1281. #ifdef MSDOS
  1282.     setmode(archive,O_BINARY);
  1283. #endif
  1284.     return 0;
  1285. }
  1286.  
  1287. /* this is a useless function that takes a buffer returned by wantbytes
  1288.    and does nothing with it.  If the function called by wantbytes returns
  1289.    an error indicator (non-zero), this function is called for the rest of
  1290.    the file.
  1291.  */
  1292. /* ARGSUSED */
  1293. int
  1294. no_op(size,data)
  1295. int size;
  1296. char *data;
  1297. {
  1298.     return 0;
  1299. }
  1300.  
  1301. /* Some other routine wants SIZE bytes in the archive.  For each chunk of
  1302.    the archive, call FUNC with the size of the chunk, and the address of
  1303.    the chunk it can work with.
  1304.  */
  1305. int
  1306. wantbytes(size,func)
  1307. long size;
  1308. int (*func)();
  1309. {
  1310.     char *data;
  1311.     long    data_size;
  1312.  
  1313.     while(size) {
  1314.         data = findrec()->charptr;
  1315.         if (data == NULL) {    /* Check it... */
  1316.             msg("Unexpected EOF on archive file");
  1317.             return -1;
  1318.         }
  1319.         data_size = endofrecs()->charptr - data;
  1320.         if(data_size>size)
  1321.             data_size=size;
  1322.         if((*func)(data_size,data))
  1323.             func=no_op;
  1324.         userec((union record *)(data + data_size - 1));
  1325.         size-=data_size;
  1326.     }
  1327.     return 0;
  1328. }
  1329.  
  1330.  
  1331. #if 0
  1332. int
  1333. rmtread(fd, buf, cnt)
  1334.     int fd;
  1335.     char *buf;
  1336.     int cnt;
  1337. {
  1338.  
  1339.     printf("rmtread(%d, %x, %d) at %x\n",
  1340.     fd, buf, cnt, lseek(fd, 0, 1));
  1341.  
  1342.     return read(fd, buf, cnt);
  1343. }
  1344. #endif
  1345.